package com.hp.docker_base.algorithm;

import lombok.Data;

import java.util.ArrayList;

@Data
public class BRBInference4 {

    ArrayList<ArrayList<Double>> reference;
    ArrayList<ArrayList<Double>> belief;
    ArrayList<ArrayList<Double>> input;

    int T;
    int K;
    int L;
    int N;
    int row1;
    int row2;

    ArrayList<Double> g = new ArrayList<>();
    ArrayList<Double> h = new ArrayList<>();
    ArrayList<Double> h1 = new ArrayList<>();
    ArrayList<ArrayList<Double>> test_membership_continuous = new ArrayList<>();
    private ArrayList<ArrayList<Double>> Activation_weight = new ArrayList<>();
    private ArrayList<ArrayList<Double>> m_xin = new ArrayList<ArrayList<Double>>();

    public BRBInference4(ArrayList<ArrayList<Double>> reference, ArrayList<ArrayList<Double>> belief, ArrayList<ArrayList<Double>> input) {
        this.reference = reference;
        this.belief = belief;
        this.input = input;
    }

    public void Init(){
        T = reference.get(0).size();
        N = belief.get(0).size();
        K = input.size();
        L = reference.size();
        row1 = input.size();
        row2 = reference.size();

        for(int i=0; i<L; i++){
            g.add(1.0);
        }
        for(int i=0; i<T; i++){
            h.add(1.0);
            h1.add(1.0);
        }


        for(int i=0; i<K; i++){
            ArrayList<Double> Temp = new ArrayList<>();
            for(int j=0; j<L; j++){
                Temp.add(1.0);
            }
            test_membership_continuous.add(Temp);
        }

    }

    public void Process(){
        ArrayList<ArrayList<Double>> test_membership_discrete = Trans_discrete(input, row1, row2, reference);
        ArrayList<ArrayList<Double>> Comprehensive = Trans_continuous_and_discrete(test_membership_continuous, test_membership_discrete, row1, row2);
        Activation_weight = weight(Comprehensive, row1, row2, g, h1);
    }
    public void fusion() {
        for(int i=0;i<row1;i++) {
            ArrayList<Double> m_xin_temp= new ArrayList<Double>();
            double b = 1.0;
            for(int k=0;k<L;k++) {
                b = b*(1-Activation_weight.get(i).get(k)*sum(belief.get(k)));
            }
            double b1 = (N - 1) * b;
            ArrayList<Double> b2 = new ArrayList<Double>();
            for(int j=0;j<N;j++) {
                double b3 = 1.0;
                for(int k=0;k<L;k++) {
                    b3 = b3 *(Activation_weight.get(i).get(k)*belief.get(k).get(j)+1-Activation_weight.get(i).get(k)*sum(belief.get(k)));
                }
                b2.add(b3);
            }
            double u = 1.0 / (sum(b2) - b1);

            double c = 1.0;
            for(int k=0;k<L;k++) {
                c = c*(1-Activation_weight.get(i).get(k));
            }
            for(int j=0;j<N;j++) {
                m_xin_temp.add(u*(b2.get(j)-b)/(1.0-u*c));
            }
            m_xin.add(m_xin_temp);
        }

    }


    public static Double sum(ArrayList<Double> data) {  //求和
        Double sum = 0.0;
        for (Double value : data) {
            sum += value;
        }
        return sum;
    }

    public ArrayList<Double> abs(ArrayList<Double> data) {  //绝对值
        ArrayList<Double> data2 = new ArrayList<Double>();
        for (Double value : data) {
            if (value < 0) {
                value = -value;
            }
            data2.add(value);
        }
        return data2;
    }

    public Double abs(Double data) {
        if (data < 0) {
            return -data;
        } else {
            return data;
        }
    }

    public static ArrayList<ArrayList<Double>> transp(ArrayList<ArrayList<Double>> input) {  //转置
        ArrayList<ArrayList<Double>> output = new ArrayList<ArrayList<Double>>();
        for (int j = 0; j < input.get(0).size(); j++) {
            ArrayList<Double> temp = new ArrayList<Double>();
            for (int i = 0; i < input.size(); i++) {
                temp.add(input.get(i).get(j));
            }
            output.add(temp);
        }
        return output;
    }

    public ArrayList<ArrayList<Double>> Trans_discrete(ArrayList<ArrayList<Double>> input, int row1, int row2, ArrayList<ArrayList<Double>> discrete_rule) {

        ArrayList<ArrayList<Double>> s = new ArrayList<ArrayList<Double>>();

        for (int i=0;i<row1;i++) {
            ArrayList<Double> Temp = new ArrayList<Double>();
            for(int j=0;j<row2;j++) {
                ArrayList<Double> c = new ArrayList<Double>();
                for(int z=0;z<input.get(i).size();z++) {
                    if(abs(input.get(i).get(z) - discrete_rule.get(j).get(z)) < 0.001 ) {
                        c.add(1.0);
                    }
                }
                Temp.add(sum(c));
            }
            s.add(Temp);
        }

        ArrayList<ArrayList<Double>> b = new ArrayList<ArrayList<Double>>();
        for(int i=0;i<row1;i++) {
            ArrayList<Double> Temp = new ArrayList<Double>();
            for(int j=0;j<row2;j++) {
                Temp.add(s.get(i).get(j)/sum(s.get(i)));
            }
            b.add(Temp);
        }

        ArrayList<ArrayList<Double>> test_membership_discrete = transp(b);

        return test_membership_discrete;
    }

    public ArrayList<ArrayList<Double>> Trans_continuous_and_discrete(ArrayList<ArrayList<Double>> test_membership_continuous, ArrayList<ArrayList<Double>> test_membership_discrete, int row1, int row2) {
        ArrayList<ArrayList<Double>> bb = transp(test_membership_continuous);
        ArrayList<ArrayList<Double>> Comprehensive = new ArrayList<ArrayList<Double>>();
        for(int i=0;i<row2;i++) {
            ArrayList<Double> Temp = new ArrayList<Double>();
            for(int j=0;j<row1;j++) {
                Temp.add(test_membership_discrete.get(i).get(j)*bb.get(i).get(j));
            }
            Comprehensive.add(Temp);
        }
        return Comprehensive;
    }

    public ArrayList<ArrayList<Double>> weight(ArrayList<ArrayList<Double>> Comprehensive, int row1, int row2, ArrayList<Double> g, ArrayList<Double> h1) {
        ArrayList<ArrayList<Double>> Activation = new ArrayList<ArrayList<Double>>();
        ArrayList<ArrayList<Double>> transp = transp(Comprehensive);
        ArrayList<ArrayList<Double>> Comprehensive_temp = new ArrayList<ArrayList<Double>>();
        for(int i=0;i<transp.size();i++) {
            ArrayList<Double> Temp = new ArrayList<Double>();
            for (int j=0;j<transp.get(i).size();j++) {
                Temp.add(Math.pow(transp.get(i).get(j),h1.get(T-1)));
            }
            Comprehensive_temp.add(Temp);
        }

        for(int i=0;i<row2;i++) {
            ArrayList<Double> Temp = new ArrayList<Double>();
            for(int j=0;j<row1;j++) {
                Temp.add(g.get(i)*(Math.pow(Comprehensive.get(i).get(j),h1.get(T-1)))/(g.get(i)*(sum(Comprehensive_temp.get(j)))));
            }
            Activation.add(Temp);
        }
        ArrayList<ArrayList<Double>> bb = transp(Activation);

        return bb;
    }

}
